package online.longzipeng.cinemasys.config;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.Data;
import online.longzipeng.cinemasys.dto.customer.CustomerLoginResponseDTO;
import online.longzipeng.cinemasys.dto.sysuser.SysUserLoginResponseDTO;
import online.longzipeng.cinemasys.entity.Customer;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * @uthor: lzp
 * @Date: 2021/2/7 15:43
 * 配置将对象生成加密的JSON字符串
 */
@Component
@Data
@ConfigurationProperties(prefix = "config.jwt")
public class JWTConfig {

    private String secret;
    private long expire;
    private static final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

    /**
     * 管理端
     *  把指定的 UserDTO 对象 生成 token[jwt]
     */
    public String generateJwtAdmin(SysUserLoginResponseDTO member){

        // 加密
        byte[] keyBytes = secret.getBytes();
        // 获得密钥对象
        SecretKey key = Keys.hmacShaKeyFor(keyBytes);
        String token = Jwts.builder()
                .setHeaderParam("typ", "JWT") //令牌类型
                //.setHeaderParam("alg", "HS256") //签名算法
                .setIssuedAt(new Date()) //签发时间
                .setExpiration(new Date(System.currentTimeMillis() + expire*1000)) //过期时间
                .claim("id", member.getId())
                .claim("nick", member.getNick())
                .claim("avatar",member.getAvatar())
                .claim("lastLoginTime",df.format(member.getLastLoginTime()))  // jwt会把时间转换为hashmap，转回时报错，故采用字符串中转
                .claim("lastLoginIp",member.getLastLoginIp())
                .signWith(key, SignatureAlgorithm.HS256).compact();
        return token;
    }

    /**
     * 客户端
     */
    public String generateJwtWeb(CustomerLoginResponseDTO member){
        // 加密
        byte[] keyBytes = secret.getBytes();
        // 获得密钥对象
        SecretKey key = Keys.hmacShaKeyFor(keyBytes);
        String token = Jwts.builder()
                .setHeaderParam("typ", "JWT") //令牌类型
                //.setHeaderParam("alg", "HS256") //签名算法
                .setIssuedAt(new Date()) //签发时间
                .setExpiration(new Date(System.currentTimeMillis() + expire*1000)) //过期时间
                .claim("id", member.getId())
                .claim("nick", member.getNick())
                .claim("avatar",member.getAvatar())
                .claim("lastLoginTime",df.format(member.getLastLoginTime()))  // jwt会把时间转换为hashmap，转回时报错，故采用字符串中转
                .claim("lastLoginIp",member.getLastLoginIp())
                .signWith(key, SignatureAlgorithm.HS256).compact();
        return token;
    }

    /**
     * 解析管理端jwt
     * @param jwtToken
     * @return
     */
    public SysUserLoginResponseDTO checkJwtAdmin(String jwtToken){

        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(this.secret.getBytes()).parseClaimsJws(jwtToken);
        // map
        Claims claims = claimsJws.getBody();
        Long id = claims.get("id",Long.class);
        String nickName = claims.get("nick",String.class);
        String avatar = claims.get("avatar",String.class);
        String lastLoginTimeStr = claims.get("lastLoginTime", String.class);
        LocalDateTime lastLoginTime = LocalDateTime.parse(lastLoginTimeStr, df);
        String lastLoginIp = claims.get("lastLoginIp", String.class);


        return SysUserLoginResponseDTO.builder()
                .id(id)
                .nick(nickName)
                .avatar(avatar)
                .lastLoginTime(lastLoginTime)
                .lastLoginIp(lastLoginIp)
                .build();
    }

    /**
     * 解析客户端jwt字符串
     */
    public CustomerLoginResponseDTO checkJwtWeb(String jwtToken){

        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(this.secret.getBytes()).parseClaimsJws(jwtToken);
        // map
        Claims claims = claimsJws.getBody();
        Long id = claims.get("id",Long.class);
        String nickName = claims.get("nick",String.class);
        String avatar = claims.get("avatar",String.class);
        String lastLoginTimeStr = claims.get("lastLoginTime", String.class);
        LocalDateTime lastLoginTime = LocalDateTime.parse(lastLoginTimeStr, df);
        String lastLoginIp = claims.get("lastLoginIp", String.class);


        return CustomerLoginResponseDTO.builder()
                .id(id)
                .nick(nickName)
                .avatar(avatar)
                .lastLoginTime(lastLoginTime)
                .lastLoginIp(lastLoginIp)
                .build();
    }

}
